package bg.btanev.eightyfour.gwtfacade.commandhandler;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.Validate;

import bg.btanev.eightyfour.domain.Tag;
import bg.btanev.eightyfour.domain.Target;
import bg.btanev.eightyfour.domain.profile.ProfileEvent;
import bg.btanev.eightyfour.domain.profile.feed.FeedMediaContent;
import bg.btanev.eightyfour.domain.profile.feed.FeedProfileEvent;
import bg.btanev.eightyfour.gwtfacade.converter.DtoConverter;
import bg.btanev.eightyfour.service.ProfileService;
import bg.btanev.eightyfour.service.TargetService;
import bg.btanev.eightyfour.shared.command.CommandResult;
import bg.btanev.eightyfour.shared.command.profileevent.FindProfileEventsCommand;
import bg.btanev.eightyfour.shared.command.profileevent.FindProfileEventsInput;
import bg.btanev.eightyfour.shared.dto.TagDto;
import bg.btanev.eightyfour.shared.dto.TargetDto;
import bg.btanev.eightyfour.shared.dto.dtobase.DomainDto;
import bg.btanev.eightyfour.shared.dto.profile.ProfileEventDto;
import bg.btanev.eightyfour.shared.dto.profile.feed.FeedProfileEventDto;
import bg.btanev.eightyfour.shared.state.ProfileType;

/**
 *
 * @author B.Tanev
 *
 */
public class FindProfileEventCommandHandler
		extends
		GenericCommandHandler<FindProfileEventsInput, ArrayList<? extends ProfileEventDto>, CommandResult<FindProfileEventsInput, ArrayList<? extends ProfileEventDto>>, FindProfileEventsCommand> {

	private final ProfileService profileService;
	private final TargetService targetService;
	private final DtoConverter converter;

	public FindProfileEventCommandHandler(ProfileService profileService, TargetService targetService,
			DtoConverter converter) {
		super();

		Validate.notNull(profileService);
		Validate.notNull(targetService);
		Validate.notNull(converter);

		this.profileService = profileService;
		this.targetService = targetService;
		this.converter = converter;
	}

	@SuppressWarnings("unchecked")
	@Override
	protected ArrayList<? extends ProfileEventDto> doExecuteInternal(FindProfileEventsInput attachedInput) {
		Validate.notNull(attachedInput);

		ArrayList<DomainDto> result = null;

		TargetDto targetDto = attachedInput.getTarget();
		Validate.notNull(targetDto);

		Long targetId = targetDto.getId();
		Validate.notNull(targetId);
		Validate.isTrue(targetId.longValue() > 0);

		Target target = targetService.findByIdentifier(targetId);
		if (target != null) {
			Date beginDate = attachedInput.getBeginDate();
			Date endDate = attachedInput.getEndDate();
			String searchQuery = attachedInput.getQuery();
			ProfileType profileType = attachedInput.getProfileType();

			List<String> tags = null;
			List<TagDto> tagDtos = attachedInput.getTags();
			if (tagDtos != null && tagDtos.size() > 0) {
				tags = new ArrayList<String>(tagDtos.size());

				for (TagDto tagDto : tagDtos) {
					tags.add(tagDto.getId());
				}
			}

			List<ProfileEvent> profileEvents = null;
			if (beginDate == null && endDate == null && searchQuery == null && tags == null && profileType == null) {
				// default search only for target
				profileEvents = profileService.findProfileEventsForTarget(target);
			} else {
				// detailed profile events search
				profileEvents = profileService.findProfileEvents(target, beginDate, endDate, profileType, searchQuery,
						tags);
			}

			if (profileEvents != null) {
				result = converter.collectionDomainToDto(profileEvents, 2);

				if (result != null && profileEvents.size() == result.size()) {
					for (int i = 0; i < result.size(); i++) {
						ProfileEvent profileEvent = profileEvents.get(i);
						ProfileEventDto profileEventDto = (ProfileEventDto) result.get(i);

						// coping tags
						Set<Tag> peTags = profileEvent.getTags();
						if (peTags != null && peTags.size() > 0) {
							Set resultTags = converter.collectionDomainToDto(peTags, 0);
							profileEventDto.setTags(resultTags);
						}

						if (profileEvent instanceof FeedProfileEvent && profileEventDto instanceof FeedProfileEventDto) {
							FeedProfileEvent feedPe = (FeedProfileEvent) profileEvent;
							FeedProfileEventDto feedPeDto = (FeedProfileEventDto) profileEventDto;

							List<FeedMediaContent> mediaContent = feedPe.getMediaContent();
							if (mediaContent != null && mediaContent.size() > 0) {
								List mediContentDtoResult = converter.collectionDomainToDto(mediaContent, 1);

								feedPeDto.setMediaContent(mediContentDtoResult);
							}
						}
					}
				}
			}
		}

		return (ArrayList<? extends ProfileEventDto>) result;
	}

	@Override
	protected CommandResult<FindProfileEventsInput, ArrayList<? extends ProfileEventDto>> packCommandResult(
			FindProfileEventsInput input, ArrayList<? extends ProfileEventDto> detachedResult) {

		return new CommandResult<FindProfileEventsInput, ArrayList<? extends ProfileEventDto>>(input, detachedResult);
	}

	@Override
	public FindProfileEventsInput attach(FindProfileEventsInput input) {
		return input;
	}

	@Override
	public ArrayList<? extends ProfileEventDto> detach(ArrayList<? extends ProfileEventDto> result) {
		return result;
	}

}
